<?php

namespace CMB\XFT;

use CMB\Common\BuilderBase;
use CMB\Common\Encrypt\SMEncrypt;
use CMB\Http\RequestParameter;
use CMB\Http\Response;
use Exception;
use CMB\Common\Encrypt\RSAEncrypt;
use FG\ASN1\ASNObject;
use Rtgm\sm\RtSm2;


class Builder extends BuilderBase
{
    protected $gateway = '';

    /**
     * Open API 平台应用编号
     * @var string $appId
     */
    protected $appId = '';

    /**
     * Open API 平台应用秘钥
     * @var string $app_secret
     */
    protected $app_secret = '';

    /**
     * sOpen API 平台上传的SM2 公钥对应的私钥
     * @var  $sm2PrivateKey
     */
    protected $sm2PrivateKey;

    /**
     * 薪福通应用 ID
     * @var  $xftAppId
     */
    protected $xftAppId;

    /**
     * 薪福通应用秘钥
     * @var  $xftAppSecret
     */
    protected $xftAppSecret;

    /**
     * 薪福通企业号
     * @var  $companyId
     */
    protected $companyId;

    /**
     * 接口无特别要求填写 默认值： AUTO0001
     * @var  $usrUid
     */
    protected $usrUid = 'AUTO0001';

    /**
     * 接口无特别要求填写 默认值： A0001
     * @var  $usrNbr
     */
    protected $usrNbr = 'A0001';

    protected $javaHome = '';

    protected $jarPath = '';

    protected $url = '';

    /**
     * 拼接请求地址
     * @param string $path
     * @param array $param
     * @return void
     */
    private function createUrl(string $path, array $param)
    {
        $this->url = $this->gateway . $path . '?' . http_build_query($param);
    }

    /**
     * 执行请求--构建请求请求参数
     * @param RequestParameter $requestParameter
     * @return Response
     */
    public function execute(RequestParameter $requestParameter): Response
    {

        try {
            $time = time();
            $microTime = $time . rand(100, 999);

            //公共参数
            $getParam = [
                'CSCAPPUID' => $this->xftAppId,
                'CSCPRJCOD' => $this->companyId,
                'CSCUSRUID' => $this->usrUid,
                'CSCREQTIM' => $microTime,
                'CSCUSRNBR' => $this->usrNbr,
//                'CSCSIGN' => $signString //签名
            ];

            //调用Java 生成加密数据获取 sign apisign CSSign
            $postParam = $requestParameter->generate();

            if (is_string($postParam) or is_int($postParam) or is_float($postParam)) {
                $requestParameter->setParameter($postParam);
            } else {
                $postParam = json_encode($postParam, JSON_UNESCAPED_UNICODE);
            }

            $javaCommand = $this->javaExecCommand($requestParameter->getPath(), $postParam, $microTime);

            $encrypt = exec($javaCommand);

            $encrypt = json_decode((string)$encrypt, true);
            if (!$encrypt) {
                throw new  Exception('Java call fail');
            }

            $header = [
                'appid' => $this->appId,
                'timestamp' => $time,
                'sign' => $encrypt['sign'],
                'apisign' => $encrypt['apisign'],
                'verify' => 'SM3withSM2'
            ];

            $getParam['CSCSIGN'] = $encrypt['CSSign'];

            $this->createUrl($requestParameter->getPath(), $getParam);

            $requestParameter->setHeaders($header);

            return $this->request($requestParameter);
        } catch (Exception $exception) {
            $message = $exception->getMessage() ?: 'java call fail2';
            return $this->exceptionResponse($requestParameter->getResponse(), $message);
        }
    }

    /**
     * 请求参数生成
     * @param RequestParameter $requestParameter
     * @return array
     * @author xis
     */
    public function generate(RequestParameter $requestParameter): array
    {
        return $requestParameter->generate();
    }

    /**
     * @param $path
     * @param $postParam
     * @param $time
     * @return string
     * @throws Exception
     */
    private function javaExecCommand($path, $postParam, $time): string
    {

        if (!$this->javaHome or !$this->jarPath) {
            throw new \Exception('java_home and jar path not setting');
        }

        return $this->javaHome . ' -Dfile.encoding=UTF-8 -DXftAppId=' . $this->xftAppId . ' -DCompanyId=' . $this->companyId . ' -DUsrUid=' . $this->usrUid . ' -DUsrNbr=' . $this->usrNbr . ' -DPath=' . $path . ' -DAppId=' . $this->appId . ' -DAppSecret=' . $this->app_secret . ' -DXftAppSecret=' . $this->xftAppSecret . ' -DPrivateKeyStr=' . $this->sm2PrivateKey . ' -DRequestBodyParam=' . base64_encode($postParam) . ' -DCurrentTimeMillis=' . $time . ' -jar ' . $this->jarPath;
    }
}
